home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v2.1 / Amiga Developer CD v2.1.iso / DevInfo / Style / CodingStandards next >
Text File  |  1996-07-13  |  13KB  |  316 lines

  1.  
  2.     $Id: CodingStandards,v 1.2 1996/07/13 20:51:24 heinz Exp $
  3.  
  4. Some rules programmers should adhere to
  5. =======================================
  6.  
  7. The zeroeth law of C programming:
  8. ---------------------------------
  9.  
  10. 0. Fully agree on the coding rules BEFORE you start the project and make
  11.    them available IN WRITING. Revise them as necessary in a group effort
  12.    and document reasons for changing them.
  13.  
  14.  
  15. First a few comments about looks and braces:
  16. --------------------------------------------
  17.  
  18. - BE CONSISTENT. No matter what coding style you choose, use it
  19.   consistently. READABILITY COUNTS.
  20.  
  21. - BE CAREFUL ABOUT TABS IN YOUR SOURCES. Tabs can be the most
  22.   obnoxious things in the world. They can even shut down your work
  23.   or at least waste valuable resources. Why? Because nobody cares
  24.   about the details. Due to historical reasons the tab character
  25.   should represent eight spaces. To be exact it should represent a
  26.   move to the next column with its number being a multiple of eight.
  27.   This value of eight spaces is very important as it is THE ONLY
  28.   value where portability including all alignment of the sources
  29.   between different OS or editing environments can be guaranteed.
  30.  
  31.   It is common practice to use tabs to indent sources. That is most
  32.   definitely not a bad thing. Unfortunately most brain damaged
  33.   editing environments allow arbitrary configuration of the tab
  34.   width for the display and then save these "display tabs" as "disk
  35.   tabs". This messes up all alignment once the next team member
  36.   loads the source into his favourite editing environment. This can
  37.   decrease readability to almost zero, and it is guaranteed that
  38.   people will get into a "formatting war" instead of doing the job
  39.   necessary. Obviously this is a totally unacceptable situation.
  40.   There is only one solution:
  41.  
  42.     Configure your editing environment to differentiate between
  43.     "disk tabs" of eight spaces and "screen tabs". You work with
  44.     screen tabs and your environment will have to automatically
  45.     convert between your favourite screen tab setting to the disk
  46.     tab size of 8 whenever it writes documents to disk. Of course
  47.     on loading an appropriate conversion to screen tabs has to take
  48.     place, too. If the environment does not support something like
  49.     this, trash it or don't use tabs in any source at all.
  50.     Otherwise you WILL have a problem.
  51.  
  52.   Concerning screen tab expansion, I strongly recommend a setting
  53.   of four. This allows for easy and efficient conversion to disk
  54.   tabs and gives a visually effective indent in pretty much any
  55.   programming language.
  56.  
  57.   Be extremely carful about automatic tab conversions in your
  58.   editing environment. If there is any chance that other members of
  59.   your team have to access the sources, automatic tab conversion
  60.   should be disabled. Otherwise the usefulness of any revision
  61.   control system in development is severly limited as the sources
  62.   will change "randomly" between certain tabs and space
  63.   configurations.
  64.  
  65. - MARK THE CLOSING BRACES WITH COMMENTS! Once you have seen >10 "END" or
  66.   "}" statements in a row and spent >10 minutes to figure out where they
  67.   belong, you know what I mean. Never just write "}" and nothing
  68.   more, write "} /* if */" or "} /* function_foo */". This is
  69.   important. Modern editing environments can be configured to do
  70.   this automatically for you.
  71.  
  72. - Having matching braces (as opposed to the K&R style) aligned in one
  73.   column makes finding the matching brace a lot easier. The brain
  74.   gets 87% of its outside information via the eyes. Simple
  75.   improvements in readability like this will save time.
  76.  
  77.   Example of a coding style concentrating on readability:
  78.  
  79.     void function(int foo, int bar)
  80.     {
  81.         switch(foo)
  82.         {
  83.             case 1:
  84.                 if(bar == 2)
  85.                 {
  86.                     /* Do something about it! */
  87.                 } /* if */
  88.                 break;
  89.             default:
  90.                 break;
  91.         } /* switch */
  92.  
  93.     } /* function */
  94.  
  95.   Naming a closing brace (or an #endif statement) as described
  96.   above helps matching them even further, especially when moving
  97.   through code of a team member.
  98.  
  99. - ALWAYS USE BRACES, even for single statements. This helps avoiding errors
  100.   when code is revised and statements are added.
  101.  
  102.     if(bla)
  103.         foo = test(foo);
  104.     else
  105.         foo = test2(foo);
  106.  
  107.   is MUCH more error prone than:
  108.  
  109.     if(bla)
  110.     {
  111.         foo = test(foo);
  112.     }
  113.     else
  114.     {
  115.         foo = test2(foo);
  116.     } /* if */
  117.  
  118.   With braces, changing code is less dangerous. Without braces it
  119.   can be very easy to get lost and to overlook a statement
  120.   dependency when you have to work with code of some other team
  121.   member. Safety counts and helps to avoid delays and expensive bug
  122.   fix releases "just because someone overlooked a semicolon" or
  123.   because of a similar stupid reason.
  124.  
  125. - DO NOT FAKE OTHER LANGUAGES, e.g. PASCAL BEHAVIOUR. Redefining e.g.
  126.   "{"/"/" as "BEGIN"/"END" with the preprocessor is IMHO a misuse of the
  127.   language. To the experienced it is as misleading as to beginners, and non
  128.   standard constructs reduce readability because "nobody" knows about them.
  129.   Using the language as it was defined allows your team to stay with
  130.   standard references and manuals. If someone does not _want_ to use a
  131.   language as is and _insists_ on aliasing its constructs to his favourite
  132.   thing, he/she'd be better in some other place. This person will probably
  133.   misuse any language. Using a screwdriver as a hammer does not lead to
  134.   results.
  135.  
  136. - LIMIT FUNCTION SIZE. Once the text of a function is much more than e.g.
  137.   two screen sizes, split it up into subfunctions. Huge functions make
  138.   revisions and maintenance a pain. Typically, performance isn't an
  139.   issue here and link time is less than compile time.
  140.  
  141. - LIMIT FILE SIZE. A C source file should never be longer than a
  142.   few hundred lines. 1k lines is the absolute upper limit.
  143.   Modularity helps a lot with C, too. Consider the linking process
  144.   to be a feature.
  145.  
  146. - USE HEADER FILES. Create prototype header files and header files with the
  147.   externally needed data declarations. Use them as help for making black
  148.   box modules.
  149.  
  150. - Separate functions with some sort of header or even a simple line:
  151.  
  152. /*------------------------------------------------------------------------*/
  153.  
  154.   This makes fast reading of source files and understanding their contents
  155.   a lot easier. Don't use "bold" lines, e.g. lines made up of
  156.   asterisks '*'. Depending on the display they lose their line-like
  157.   character and clutter the screen instead of helping to make
  158.   things readable.
  159.  
  160. - Use a standard header and footer for each source file. If you are using
  161.   a Revision control system, the header should contain an identification.
  162.   This header can be quite simple:
  163.  
  164. /*------------------------------------------------------------------------*/
  165. /*                                                                        *
  166.  *  $Id: CodingStandards,v 1.2 1996/07/13 20:51:24 heinz Exp $
  167.  *                                                                        */
  168. /*------------------------------------------------------------------------*/
  169.  
  170. /*------------------------------------------------------------------------*/
  171. [headers here]
  172.  
  173. /*------------------------------------------------------------------------*/
  174. [code here]
  175.  
  176. /*------------------------------------------------------------------------*/
  177.  
  178. /* End of Text */
  179.  
  180.  
  181.  
  182.  
  183. Now some comments on use of the language and compiler:
  184. ------------------------------------------------------
  185.  
  186. - USE THE ANSI C STANDARD for declarations. Avoid K&R wherever possible.
  187.   The compiler is your friend and will do better error checking
  188.   with ANSI prototypes.
  189.  
  190. - ALWAYS RUN the compiler system with THE STRICTEST ERROR CHECKING MODE
  191.   possible. C compilers have limits to their diagnostic ability, so use what
  192.   is available. ERRORS AND WARNINGS ARE NOT ACCEPTABLE!
  193.  
  194. - READ THE "IMPLEMENTATION-DEFINED BEHAVIOUR" SECTION OF THE MANUAL BEFORE
  195.   YOU START. While there is a standard for C, there are still things that
  196.   can bite you if you are not aware of them. ANSI C does not
  197.   automatically mean "great, portable, and future compatible".
  198.  
  199. - HAVE THE LANGUAGE DEFINITION IN REACH FOR ALL TEAM MEMBERS. I also
  200.   recommend having a book like "P.J.Plaugher: The Standard C Library"
  201.   around as reference to everyone on the team. IF IN DOUBT, LOOK IT UP! IT
  202.   IS NOT A SHAMEFUL THING TO DO!
  203.  
  204. - STAY WITH STANDARDS WHEREVER POSSIBLE. If you write a standard
  205.   C application use the standard ANSI library. If you write
  206.   something specific to a certain OS, use the tools the OS
  207.   provides. Avoid arbitrary mixtures of standard C and OS specific
  208.   C. Avoid use of functions specific to your current C compiler
  209.   system or specific to the HW if you want to have protable code.
  210.   You might need to change both eventually. This is mostly a
  211.   problem for IBM clone programmers who think that "Borland C++" or
  212.   "MS C++" and clones is the only thing there is in the world.
  213.   Watch your team. Check what your compiler does per default with
  214.   newlines or character sets! "\r\n" vs. "\n" problems can be
  215.   eventually as painful as a compiler system that mangles ISO
  216.   characters into 7 bit in strange places. Note that handling
  217.   binary file data is different than text data with the ANSI C
  218.   library. Do not rely on it being the same for all compiler
  219.   systems.
  220.  
  221. - ISOLATE NON PORTABLE CODE.
  222.  
  223. - USE "const" and "volatile". Especially "const" helps the compiler and the
  224.   poor soul who writes and debugs the code a lot. Wise use of "const"
  225.   enhances the compiler error checking capabilities usually a lot.
  226.   Some compilers may generate poor code with these keywords
  227.   unfrtunately. In that case an easy solution is to define them to
  228.   nothing when generating production code.
  229.  
  230. - Define anything that does not need to be externally visible as "static".
  231.   LIMITING SCOPE of unneeded stuff helps a) the linker, b) modularity, c) a
  232.   strong black box approach for modules.
  233.  
  234. - USE THE PREPROCESSOR CAREFULLY. While it may be useful to give strange
  235.   constants nice names, use of it should be monitored. Major caveat: C is a
  236.   language where expressions often have side effects. Side effects hidden
  237.   in preprocessor macros are not diagnosed by all compiler systems! Do not
  238.   overdo it here!
  239.  
  240. - If a source file has self contained functionality like e.g time
  241.   conversion stuff, think hard about ADDING A TEST CASE FOR CONDITIONAL
  242.   COMPILE in the first place.
  243.  
  244.     #ifdef TEST
  245.     int main(int argc, const char **argv)
  246.     {
  247.         /* test the darn thing here! */
  248.     } /* main */
  249.     #endif /* TEST */
  250.  
  251. - REMEMBER: THE LINKER IS YOUR FRIEND!
  252.  
  253. - If your compiler system has an automatic build facility like "make", use
  254.   it. "make" is a very helpful tool. If you have some sort of custom
  255.   integrated compiler  environment, make sure that you can comparatively
  256.   easy fall back on a standard make like scheme. Be careful about
  257.   all the different incarnations of "make". KEEP THE PARACHUTE
  258.   CLOSE.
  259.  
  260. - C IS USUALLY MOST EFFICIENT WHEN USED WITH POINTERS. Passing data
  261.   structures is not good, most things are done with pointers. If your team
  262.   does not have a FIRM UNDERSTANDING OF POINTERS, teach them first. Don't
  263.   let them fiddle along. They need to know first or you might be in deep
  264.   trouble.
  265.  
  266. - CHECK FUNCTION RESULTS FOR ANY FUNCTION THAT MAY FAIL. A common error is
  267.   not checking for failure on e.g. memory allocations. ASSUME A NEGATIVE
  268.   SITUATION when writing the code. It will hardly ever be a performance hit
  269.   if you do and increase reliability.
  270.  
  271.  
  272. Comments about debugging C:
  273. ---------------------------
  274.  
  275. - CHECK FOR NULL POINTERS AND POINTER OVERRUNS.
  276.  
  277. - C STRINGS HAVE A TRAILING NULL BYTE AND ARE THEREFORE ONE BYTE LONGER
  278.   THAN THE CONTENTS!
  279.  
  280. - CHECK FOR MISSING "*/" END OF COMMENTS. YOU MIGHT HAVE LOST A LINE OF
  281.   CODE.
  282.  
  283. - If a bug is still hiding and can't be found, have the author explain the
  284.   functionality of the code in question line by line including limit and
  285.   exception handling to someone on the team who is not directly involved in
  286.   this part of the project. This will usually solve the problem pretty
  287.   fast and save additional cost.
  288.  
  289.  
  290. And now something short on code management:
  291. -------------------------------------------
  292.  
  293. - USE some sort of A REVISION CONTROL SYSTEM like RCS, CVS, SCCS ...
  294.   PUT A FILE ID COMMENT (like the RCS 'Id' keyword) INTO EACH
  295.   SOURCE FILE. Otherwise identifying a printed revision is pretty
  296.   much impossible once you get swamped in paper. I use RCS. Do not
  297.   ever use expanding 'Log' like keywords in your sources. They just
  298.   duplicate what is in the repository already and they'll make
  299.   identifying differences even harder. After a while they also
  300.   clutter the source.
  301.  
  302. - Mark stable revisions and flame everyone who makes too many changes to
  303.   the code before using the revision control system to check it in again.
  304.   There should not be any work files not being checked in lying around at
  305.   the end of a working day!
  306.  
  307.  
  308. last but not least: Have fun.
  309.  
  310. Heinz Wrobel
  311. Karlstr. 16
  312. 82131 Gauting
  313. FAX +49 89 850 5125
  314. <heinz@hwg.muc.de>
  315.  
  316.